package com.uinnova.product.eam.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.binary.framework.exception.ServiceException;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.uinnova.product.eam.base.model.ModuleFieldInfo;
import com.uinnova.product.eam.base.model.SpecificationAppendix;
import com.uinnova.product.eam.base.model.SpecificationInfo;
import com.uinnova.product.eam.base.model.TableHeader;
import com.uinnova.product.eam.base.util.EamDiagramUtils;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.config.Env;
import com.uinnova.product.eam.db.bean.DiagramChangeData;
import com.uinnova.product.eam.model.EamArtifactElementVo;
import com.uinnova.product.eam.model.EamArtifactRltVo;
import com.uinnova.product.eam.model.EamArtifactVo;
import com.uinnova.product.eam.model.asset.EamCiRltDTO;
import com.uinnova.product.eam.model.dto.ElementDto;
import com.uinnova.product.eam.model.enums.ArtifactType;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.eam.service.fx.GeneralPushSvc;
import com.uinnova.product.eam.service.handler.PushFacadeService;
import com.uinnova.product.vmdb.comm.model.ci.*;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiInfo;
import com.uinnova.product.vmdb.provider.rlt.bean.CcCiRltInfo;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.base.diagram.comm.model.ESDiagramDTO;
import com.uinnova.project.base.diagram.comm.model.ESDiagramInfoDTO;
import com.uinnova.project.base.diagram.comm.model.ESDiagramNode;
import com.uinnova.project.db.eam.ESDiagramNodeDao;
import com.uinnova.project.model.diagram.event.DiagramRuleEnum;
import com.uinnova.project.model.diagram.event.RuleParams;
import com.uino.api.client.cmdb.ICIClassApiSvc;
import com.uino.api.client.cmdb.IRltClassApiSvc;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.cmdb.business.BindCiRltRequestDto;
import com.uino.bean.cmdb.query.ESCISearchBean;
import com.uino.bean.cmdb.query.ESRltSearchBean;
import com.uino.bean.permission.base.SysUser;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 业务组件实现
 *
 * @author zdh_c
 */
@Service
@Slf4j
public class BmModuleSvcImpl implements BmModuleSvc {

    @Resource
    ESDiagramApiClient diagramApiClient;

    @Resource
    private EamCategorySvc categorySvc;
    @Resource
    ICISwitchSvc ciSwitchSvc;

    @Resource
    ICIClassApiSvc iciClassApiSvc;

    @Resource
    private BmConfigSvc bmConfigSvc;

    @Resource
    IEamArtifactSvc eamArtifactSvc;

    @Resource
    IamsCIRltSwitchSvc ciRltSwitchSvc;

    @Resource
    IamsCIRltPrivateSvc iamsCIRltPrivateSvc;

    @Resource
    IEamArtifactColumnSvc eamArtifactColumnSvc;

    @Resource
    private IRltClassApiSvc rltClassApiSvc;

    @Resource
    FxDiagramSvc fxDiagramSvc;

    @Resource
    ESDiagramNodeDao iamsEsDiagramNodeDao;

    @Resource
    GeneralPushSvc generalPushSvc;

    @Override
    public List<ESCIInfo> queryBelongToDomainByTask(String diagramId) {
        JSONObject componentConfig = bmConfigSvc.getBusComponentConfig();
        if (BinaryUtils.isEmpty(componentConfig)) {
            throw new ServiceException("缺少业务组件相关配置:BUS_COMPONENT_CONFIG,请添加！");
        }
        String domainClsName = componentConfig.getString(Env.BM_DOMAIN);
        String taskClsName = componentConfig.getString(Env.BM_TASK);
        String componentName = componentConfig.getString(Env.BM_COMPONENT);
        if(BinaryUtils.isEmpty(domainClsName) || BinaryUtils.isEmpty(taskClsName)){
            throw new BinaryException("缺少查找配置项");
        }
        CCcCiClass cdt = new CCcCiClass();
        cdt.setClassNames(new String[]{domainClsName, taskClsName, componentName});
        List<CcCiClassInfo> classList = iciClassApiSvc.queryClassByCdt(cdt);
        if(CollectionUtils.isEmpty(classList) || classList.size()<cdt.getClassNames().length){
            throw new BinaryException("缺少对象分类数据:"+ Arrays.toString(cdt.getClassNames()));
        }
        Map<String, Long> classMap = classList.stream().map(CcCiClassInfo::getCiClass).collect(Collectors.toMap(CcCiClass::getClassName, CcCiClass::getId));
        //1.查询图中定义任务
        Long id = diagramApiClient.queryDiagramInfoByEnergy(diagramId);
        if (BinaryUtils.isEmpty(id)) {
            throw new ServiceException("视图不存在！");
        }
        List<ESDiagramNode> esDiagramNodes = diagramApiClient.selectNodeByDiagramIds(Collections.singletonList(id));
        List<String> ciCodes = esDiagramNodes.stream().map(ESDiagramNode::getCiCode).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if(BinaryUtils.isEmpty(ciCodes)){
            return Collections.emptyList();
        }
        Long taskClassId = classMap.get(taskClsName);
        Long componentClassId = classMap.get(componentName);
        List<ESCIInfo> ciInfoList = ciSwitchSvc.getCiByCodes(ciCodes, null, LibType.DESIGN);
        if (CollectionUtils.isEmpty(ciInfoList)) {
            return Collections.emptyList();
        }
        List<String> taskCiCodes = ciInfoList.stream().filter(each -> each.getClassId().equals(taskClassId)).map(CcCi::getCiCode).distinct().collect(Collectors.toList());
        // 用户名下节点过多 使用滚动查询
        List<ESDiagramNode> nodeList = iamsEsDiagramNodeDao.getListByQueryScroll(QueryBuilders.termsQuery("ciCode.keyword", taskCiCodes));
        Set<Long> diagramIdList = nodeList.stream().map(ESDiagramNode::getDiagramId).collect(Collectors.toSet());
        List<ESDiagram> diagramList = diagramApiClient.getByIds(diagramIdList, null, Lists.newArrayList(1));
        if (CollectionUtils.isEmpty(diagramList)) {
            return Collections.emptyList();
        }
        List<EamCategory> categoryDesignList = categorySvc.selectByModelId(null, LibType.DESIGN, null);
        Map<String, EamCategory> diagramCatalogDict = new HashMap<>(16);
        Map<Long, EamCategory> dirCodeCatalogDict = new HashMap<>(16);
        List<String> ciCodeList = new ArrayList<>();
        for (EamCategory each : categoryDesignList) {
            if(!BinaryUtils.isEmpty(each.getDiagramId()) && !BinaryUtils.isEmpty(each.getCiCode())){
                ciCodeList.add(each.getCiCode());
                diagramCatalogDict.put(each.getDiagramId(), each);
            }
            dirCodeCatalogDict.put(each.getId(), each);
        }
        List<ESCIInfo> ciList = ciSwitchSvc.getCiByCodes(ciCodeList, null, LibType.DESIGN);
        Map<String, Long> ciCodeNameMap = ciList.stream().collect(Collectors.toMap(CcCi::getCiCode, CcCi::getClassId, (k1, k2) -> k2));
        List<String> domainAssetList = new ArrayList<>(diagramList.size());
        for (ESDiagram esDiagram : diagramList) {
            EamCategory catalog = diagramCatalogDict.get(esDiagram.getDEnergy());
            if(catalog == null){
                continue;
            }
            EamCategory matchNode = findMatchNode(catalog.getId(), classMap.get(domainClsName), dirCodeCatalogDict, ciCodeNameMap);
            if(matchNode == null){
                continue;
            }
            domainAssetList.add(matchNode.getCiCode());
        }
        if(BinaryUtils.isEmpty(domainAssetList)){
            return Collections.emptyList();
        }

        List<ESCIInfo> result = ciSwitchSvc.getCiByCodes(domainAssetList, null, LibType.DESIGN);
        if (BinaryUtils.isEmpty(result)) {
            return Collections.emptyList();
        }
        List<ESCIInfo> componentCiList = ciInfoList.stream().filter(each -> each.getClassId().equals(componentClassId)).collect(Collectors.toList());
        Object defaultDomain = componentCiList.get(0).getAttrs().get("所属领域");
        if(!BinaryUtils.isEmpty(defaultDomain)){
            for (ESCIInfo each : result) {
                Object name = each.getAttrs().get("名称");
                if(!BinaryUtils.isEmpty(name) && defaultDomain.toString().equals(name.toString())){
                    each.setCustom1(defaultDomain.toString());
                }
            }
        }
        return result;
    }


    private EamCategory findMatchNode(Long dirCode, Long classId, Map<Long,EamCategory> catalogMap, Map<String, Long> ciCodeNameMap){
        if(dirCode == 0L || classId==null){
            return null;
        }
        EamCategory node = catalogMap.get(dirCode);
        if(null == node){
            throw new BinaryException("目录数据不完整");
        }
        if(ciCodeNameMap.get(node.getCiCode()).equals(classId)){
            return node;
        }
        return findMatchNode(node.getParentId(), classId, catalogMap, ciCodeNameMap);
    }


    private Long getClassIdByName(String className) {
        if (BinaryUtils.isEmpty(className)) {
            return null;
        }
        CCcCiClass cCcCiClass = new CCcCiClass();
        cCcCiClass.setClassNameEqual(className);
        List<CcCiClassInfo> ccCiClassInfos = iciClassApiSvc.queryCiClassInfoList(1L, cCcCiClass, null, false);
        if (CollectionUtils.isEmpty(ccCiClassInfos)) {
            return null;
        }
        return ccCiClassInfos.get(0).getCiClass().getId();
    }

    @Override
    public SpecificationInfo domainAndModuleSpecification(String diagramId) {
        SpecificationInfo specificationInfo = new SpecificationInfo();
        //通过分类名称获取分类信息
        JSONObject componentConfig = bmConfigSvc.getBusComponentConfig();
        if (BinaryUtils.isEmpty(componentConfig)) {
            throw new ServiceException("缺少业务组件相关配置:BUS_COMPONENT_CONFIG,请添加！");
        }
        Long domainClassId = getClassIdByName(componentConfig.getString(Env.BM_DOMAIN));
        Long taskClassId = getClassIdByName(componentConfig.getString(Env.BM_TASK));
        Long entityClassId = getClassIdByName(componentConfig.getString(Env.BM_ENTITY));
        Long processClassId = getClassIdByName(componentConfig.getString(Env.BM_PROCESS));
        Long ruleClassId = getClassIdByName(componentConfig.getString(Env.BM_RULE));
        Long objectClassId = getClassIdByName(componentConfig.getString(Env.BM_OBJECT));


        Long energy = diagramApiClient.queryDiagramInfoByEnergy(diagramId);
        ESDiagramDTO designDiagramInfo = diagramApiClient.queryESDiagramInfoById(energy, null, false);
        String loginCode = designDiagramInfo.getDiagram().getOwnerCode();
        Set<String> ciCodes = EamDiagramUtils.getDiagramCiList(Collections.singletonList(designDiagramInfo.getDiagram()));
        String label = "";
        List<CcCiInfo> moduleInfos = new ArrayList<>();
        List<CcCiInfo> taskInfos = new ArrayList<>();
        if (!BinaryUtils.isEmpty(ciCodes)) {
            //1.获取视图中的元素
            List<ESCIInfo> ciList = ciSwitchSvc.getCiByCodes(new ArrayList<>(ciCodes), loginCode, LibType.PRIVATE);
            if (CollectionUtils.isEmpty(ciList)) {
                throw new ServiceException("视图中对象信息为空");
            }
            //组件
            CCcCiClass cCcCiClass = new CCcCiClass();
            cCcCiClass.setClassNameEqual(componentConfig.getString(Env.BM_COMPONENT));
            List<CcCiClassInfo> ccCiClassInfos = iciClassApiSvc.queryCiClassInfoList(1L, cCcCiClass, null, false);
            CcCiClassInfo moduleClassInfo = ccCiClassInfos.get(0);
            //添加分类属性： 类型  1.自有组件， 2.外部组件
            Long moduleClassId = moduleClassInfo.getCiClass().getId();
            List<CcCiAttrDef> moduleAttrDefs = moduleClassInfo.getAttrDefs();
            CcCiAttrDef moduleAttr = new CcCiAttrDef();
            moduleAttr.setProName("类型");
            moduleAttr.setProStdName("类型");
            moduleAttr.setClassId(moduleClassId);
            moduleAttrDefs.add(moduleAttr);
            List<ESCIInfo> moduleList = ciList.stream().filter(esciInfo -> esciInfo.getClassId().equals(moduleClassId)).collect(Collectors.toList());
            //领域
            List<ESCIInfo> domainList = ciList.stream().filter(esciInfo -> esciInfo.getClassId().equals(domainClassId)).collect(Collectors.toList());
            if (BinaryUtils.isEmpty(domainList)) {
                List<ESCIInfo> designCiList = ciSwitchSvc.getCiByCodes(new ArrayList<>(ciCodes), null, LibType.DESIGN);
                if (CollectionUtils.isNotEmpty(designCiList)) {
                    domainList = designCiList.stream().filter(esciInfo -> esciInfo.getClassId().equals(domainClassId)).collect(Collectors.toList());
                }
                if (CollectionUtils.isEmpty(domainList) || domainList.size() > 1) {
                    throw new ServiceException("视图中领域信息不正确!!");
                }
            }
            String ciLabel = domainList.get(0).getCiLabel();
            label = PushFacadeService.extractMessageByRegular(ciLabel).get(0).replace("\"", "");

            //封装组件信息集合
            HashSet<String> moduleCiCodes = new HashSet<>();
            HashSet<String> modulePrimary = new HashSet<>();
            for (ESCIInfo esciInfo : moduleList) {
                buildModuleInfo(esciInfo, label);
                CcCiInfo ci = EamUtil.coverESCIInfo(esciInfo, EamUtil.copy(moduleAttrDefs, CcCiAttrDef.class), moduleClassInfo.getCiClass());
                moduleInfos.add(ci);
                //通过组件查询任务
                moduleCiCodes.add(esciInfo.getCiCode());
                modulePrimary.add(esciInfo.getCiPrimaryKey());
            }
            //封装任务信息
            if (!BinaryUtils.isEmpty(moduleCiCodes)) {
                ESCISearchBean bean = new ESCISearchBean();
                bean.setCiCodes(new ArrayList<>(moduleCiCodes));
                bean.setClassIds(Lists.newArrayList(moduleClassId));
                Page<ESCIInfo> designModule = ciSwitchSvc.searchESCIByBean(bean, LibType.DESIGN);
                if (CollectionUtils.isEmpty(designModule.getData()) || designModule.getData().size() < moduleCiCodes.size()) {
                    bean.setCiCodes(Collections.emptyList());
                    bean.setCiPrimaryKeys(modulePrimary);
                    designModule = ciSwitchSvc.searchESCIByBean(bean, LibType.DESIGN);
                    if (CollectionUtils.isNotEmpty(designModule.getData())) {
                        Set<String> designModuleCiCodes = designModule.getData().stream().map(CcCi::getCiCode).collect(Collectors.toSet());
                        moduleCiCodes.addAll(designModuleCiCodes);
                    }
                }
                ESRltSearchBean rltSearchBean = new ESRltSearchBean();
                rltSearchBean.setSourceCiCodes(moduleCiCodes);
                rltSearchBean.setOwnerCode(loginCode);
                rltSearchBean.setTargetClassIds(Lists.newArrayList(taskClassId));
                List<EamCiRltDTO> ciRltInfos = ciRltSwitchSvc.searchRltByRltCodes(rltSearchBean, LibType.DESIGN);
                if (CollectionUtils.isEmpty(ciRltInfos)) {
                    log.error("该组件未关联信息未创建");
                }
                //去重
                List<EamCiRltDTO> disCiInfos = ciRltInfos.stream().filter(c -> c.getTargetCiInfo().getCiClass().getId().equals(taskClassId))
                        .collect(Collectors.collectingAndThen(
                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(each -> each.getTargetCiInfo().getCi().getId()))), ArrayList::new));

                //添加任务字段-任务图中的 步骤、实体、业务对象、业务规则、关联组件
                CCcCiClass taskClass = new CCcCiClass();
                taskClass.setClassNameEqual(componentConfig.getString(Env.BM_TASK));
                List<CcCiClassInfo> taskClassInfos = iciClassApiSvc.queryCiClassInfoList(1L, taskClass, null, false);
                CcCiClassInfo taskClassInfo = taskClassInfos.get(0);
                fillTaskClassAttr(taskClassInfo);
                //获取目标端为任务的对象
                for (EamCiRltDTO ciRltInfo : disCiInfos) {
                    CcCiInfo targetCiInfo = ciRltInfo.getTargetCiInfo();
                    Map<String, String> taskInfo = targetCiInfo.getAttrs();
                    String ciCode = targetCiInfo.getCi().getCiCode();
                    //获取任务视图信息，获取任务步骤、实体、详细业务规则
//                    List<EamDiagramCatalog> catalogList = diagramCatalogSvc.selectByAssetCodes(Lists.newArrayList(ciCode), null, LibType.DESIGN);
                    List<EamCategory> categoryList = categorySvc.selectListByCiCodes(null, Lists.newArrayList(ciCode), null, LibType.DESIGN);
                    if (CollectionUtils.isEmpty(categoryList)) {
                        log.error("该任务目录结构不存在，ciCode:" + ciCode);
                        continue;
                    }
                    EamCategory catalog = categoryList.get(0);
                    //任务CI对应视图
                    String taskDiagramId = catalog.getDiagramId();
                    log.error("该任务目录下diagramId不存在，ciCode:" + ciCode);
                    if (!BinaryUtils.isEmpty(taskDiagramId)) {
                        Long diagramInfo = diagramApiClient.queryDiagramInfoByEnergy(taskDiagramId);
                        List<ESDiagramDTO> esDiagramDTOS = diagramApiClient.queryDiagramInfoByIds(new Long[]{diagramInfo}, null, false, false);
                        if (CollectionUtils.isEmpty(esDiagramDTOS)) {
                            log.error("该任务视图不存在，ciCode:" + ciCode);
                            continue;
                        }
                        ESDiagramDTO taskDiagramInfo = esDiagramDTOS.get(0);
                        Set<String> taskDiagramCiCodes = EamDiagramUtils.getDiagramCiList(Collections.singletonList(taskDiagramInfo.getDiagram()));
                        if (CollectionUtils.isEmpty(taskDiagramCiCodes)) {
                            continue;
                        }
                        ESCISearchBean esTaskBean = new ESCISearchBean();
                        esTaskBean.setPageNum(1);
                        esTaskBean.setPageSize(taskDiagramCiCodes.size());
                        esTaskBean.setCiCodes(new ArrayList<>(taskDiagramCiCodes));
                        Page<ESCIInfo> taskDiagramCIPage = ciSwitchSvc.searchESCIByBean(esTaskBean, LibType.DESIGN);
                        if (CollectionUtils.isNotEmpty(taskDiagramCIPage.getData())) {
                            List<ESCIInfo> taskCiList = taskDiagramCIPage.getData();
                            List<String> entity = new ArrayList<>();
                            List<String> process = new ArrayList<>();
                            List<String> rule = new ArrayList<>();
                            List<String> object = new ArrayList<>();
                            for (ESCIInfo esciInfo : taskCiList) {
                                if (esciInfo.getClassId().equals(entityClassId) && !BinaryUtils.isEmpty(esciInfo.getCiLabel())) {
                                    entity.add(esciInfo.getCiLabel().replace("[", "").replace("]", "").replace("\"", ""));
                                    continue;
                                }
                                if (processClassId.equals(esciInfo.getClassId()) && !BinaryUtils.isEmpty(esciInfo.getCiLabel())) {
                                    process.add(esciInfo.getCiLabel().replace("[", "").replace("]", "").replace("\"", ""));
                                    continue;
                                }
                                if (ruleClassId.equals(esciInfo.getClassId()) && !BinaryUtils.isEmpty(esciInfo.getCiLabel())) {
                                    rule.add(esciInfo.getCiLabel().replace("[", "").replace("]", "").replace("\"", ""));
                                    continue;
                                }
                                if (objectClassId.equals(esciInfo.getClassId()) && !BinaryUtils.isEmpty(esciInfo.getCiLabel())) {
                                    object.add(esciInfo.getCiLabel().replace("[", "").replace("]", "").replace("\"", ""));
                                }
                            }
                            taskInfo.put("步骤", JSON.toJSONString(process));
                            taskInfo.put("实体", JSON.toJSONString(entity));
                            taskInfo.put("业务规则", JSON.toJSONString(rule));
                            taskInfo.put("业务对象", JSON.toJSONString(object));
                        }
                    }
                    String moduleName = ciRltInfo.getSourceCiInfo().getCi().getCiLabel();
                    taskInfo.put("关联组件", moduleName);
                    targetCiInfo.setAttrDefs(taskClassInfo.getAttrDefs());
                    targetCiInfo.setAttrs(taskInfo);
                    taskInfos.add(targetCiInfo);
                }
            }
        }

        //封装附录信息
        List<SpecificationAppendix> specificationAppendices = buildAppendixInfo();
        specificationInfo.setAppendices(specificationAppendices);
        specificationInfo.setDomainName(label);
        specificationInfo.setModuleInfos(moduleInfos);
        specificationInfo.setTaskInfos(taskInfos);
        specificationInfo.setAppendicesHeader(getAppendicesHeader());
        return specificationInfo;
    }

    private void buildModuleInfo(ESCIInfo esciInfo, String domainName) {
        Map<String, Object> attrs = esciInfo.getAttrs();
        if (!BinaryUtils.isEmpty(attrs.get("所属领域"))) {
            String belongsToField = attrs.get("所属领域").toString();
            if (belongsToField.equals(domainName)) {
                attrs.put("类型", "自有组件");
            } else {
                attrs.put("类型", "外部组件");
            }
        } else {
            attrs.put("类型", "外部组件");
        }
    }

    private List<Map<String, String>> getAppendicesHeader() {
        List<Map<String, String>> appendixList = new ArrayList<>();
        for (Field appendixField : SpecificationAppendix.class.getDeclaredFields()) {
            appendixField.setAccessible(true);
            if (appendixField.isAnnotationPresent(TableHeader.class)) {
                TableHeader annotation = appendixField.getAnnotation(TableHeader.class);
                HashMap<String, String> keyValue = new HashMap<>();
                String value = annotation.value();
                if (BinaryUtils.isEmpty(value)) {
                    keyValue.put("title", appendixField.getName());
                    keyValue.put("key", appendixField.getName());
                } else {
                    keyValue.put("title", value);
                    keyValue.put("key", appendixField.getName());
                }
                appendixList.add(keyValue);
            }
        }
        return appendixList;
    }

    private List<SpecificationAppendix> buildAppendixInfo() {
        //业务组件说明书配置项
        String confJson = bmConfigSvc.getConfigType("SPECIFICATION_APPENDIX");
        if (BinaryUtils.isEmpty(confJson)) {
            throw new BinaryException("缺少基础配置项");
        }
        JSONObject jsonObject = JSON.parseObject(confJson, JSONObject.class);
        Iterator<Map.Entry<String, Object>> iterator = jsonObject.entrySet().iterator();
        List<SpecificationAppendix> appendices = new ArrayList<>();
        while (iterator.hasNext()) {
            Map.Entry<String, Object> next = iterator.next();
            SpecificationAppendix appendix = new SpecificationAppendix();
            String key = next.getKey();
            String value = next.getValue().toString();
            appendix.setName(key);
            appendix.setDefinition(value);
            appendices.add(appendix);
        }
        return appendices;
    }

    private void fillTaskClassAttr(CcCiClassInfo taskClassInfo) {
        List<CcCiAttrDef> attrDefs = taskClassInfo.getAttrDefs();
        CcCiAttrDef process = new CcCiAttrDef();
        process.setProName("步骤");
        process.setProStdName("步骤");
        process.setClassId(taskClassInfo.getCiClass().getId());
        attrDefs.add(process);
        CcCiAttrDef entity = new CcCiAttrDef();
        entity.setProName("实体");
        entity.setProStdName("实体");
        entity.setClassId(taskClassInfo.getCiClass().getId());
        attrDefs.add(entity);
        CcCiAttrDef bucObject = new CcCiAttrDef();
        bucObject.setProName("业务对象");
        bucObject.setProStdName("业务对象");
        bucObject.setClassId(taskClassInfo.getCiClass().getId());
        attrDefs.add(bucObject);
        CcCiAttrDef rule = new CcCiAttrDef();
        rule.setProName("业务规则");
        rule.setProStdName("业务规则");
        rule.setClassId(taskClassInfo.getCiClass().getId());
        attrDefs.add(rule);
        CcCiAttrDef component = new CcCiAttrDef();
        component.setProName("关联组件");
        component.setProStdName("关联组件");
        component.setClassId(taskClassInfo.getCiClass().getId());
        attrDefs.add(component);
    }

    @Deprecated
    @Override
    public String releaseModuleDiagram(String diagramId, String releaseDesc, Long dirId, String targetCiCode) {
        //1.校验视图
        Long id = diagramApiClient.queryDiagramInfoByEnergy(diagramId);
        ESDiagramDTO diagramInfo = diagramApiClient.queryESDiagramInfoById(id, null, false);
        ESDiagramInfoDTO diagram = diagramInfo.getDiagram();
        String loginCode = diagram.getOwnerCode();
        // 查询视图上的 CI / RLT 数据
        Set<String> ciCodes = EamDiagramUtils.getDiagramCiList(Collections.singletonList(diagram));
        List<DiagramChangeData> checkList = fxDiagramSvc.isCheckOScanning(Collections.singletonList(diagramId));
        if (!BinaryUtils.isEmpty(checkList)) {
            List<String> ciPrimaryKey = checkList.stream().map(diagramChangeData -> diagramChangeData.getPrivateCiInfo().getCi().getCiPrimaryKey()).collect(Collectors.toList());
            Boolean binding = fxDiagramSvc.freshBindingEleByDEnergyId(Collections.singletonList(diagramId), ciPrimaryKey, Env.GENERAL_DIAGRAM_PUBLISH);
        }
        JSONObject componentConfig = bmConfigSvc.getBusComponentConfig();
        if (BinaryUtils.isEmpty(componentConfig)) {
            throw new ServiceException("缺少业务组件相关配置:BUS_COMPONENT_CONFIG,请联系管理员!");
        }
        String releaseDiagramId = null;
        String viewType = diagram.getViewType();
        //2.校验视图中元素
        String artifactName = "";
        if (!BinaryUtils.isEmpty(viewType)) {
            EamArtifactVo queryArtifact = eamArtifactSvc.queryArtifact(Long.valueOf(viewType));
            artifactName = queryArtifact.getArtifactName();
        }
        String componentName = componentConfig.getString(Env.COMPONENT_DEFINITION_DIAGRAM);
        String domainName = componentConfig.getString(Env.DOMAIN_COMPONENT_RLT_DIAGRAM);
        if(componentName.equals(artifactName) || domainName.equals(artifactName)){
            String className = componentName.equals(artifactName) ? Env.BM_COMPONENT : Env.BM_DOMAIN;
            Long classId = getClassIdByName(componentConfig.getString(className));
            CCcCi cdt = new CCcCi();
            cdt.setCiCodes(ciCodes.toArray(new String[0]));
            cdt.setClassId(classId);
            cdt.setOwnerCodeEqual(loginCode);
            List<CcCiInfo> privateCiList = ciSwitchSvc.queryCiInfoList(1L, cdt, null, false, false, LibType.PRIVATE);
            if (BinaryUtils.isEmpty(privateCiList)) {
                throw new ServiceException("当前视图未创建"+ componentConfig.getString(className) +"对象,无法发布!");
            }
            //校验当前组件是否已发布
            String ciCode = privateCiList.get(0).getCi().getCiCode();
            if(domainName.equals(artifactName)){
                List<ESCIInfo> designCiList = ciSwitchSvc.getCiByCodes(Collections.singletonList(ciCode), null, LibType.DESIGN);
                if (BinaryUtils.isEmpty(designCiList)) {
                    throw new ServiceException("业务组件与业务领域关系管理图发布失败,设计库中不存在当前业务领域!");
                }
            }else{
                //在图中创建隐藏所属关系
                if(!BinaryUtils.isEmpty(targetCiCode)){
                    RuleParams params = new RuleParams();
                    params.setDiagramId(diagram.getId());
                    params.setRuleType(DiagramRuleEnum.COMPONENT_DIAGRAM);
                    params.setOwnerCode(diagram.getOwnerCode());
                    params.setDomainId(diagram.getDomainId());
                    params.setSheetId(diagram.getSheetList().get(0).getSheetId());
                    params.setSrcCiCode(ciCode);
                    params.setTargetCiCode(targetCiCode);
                    diagramApiClient.createHiddenLink(params);
                }
            }
            releaseDiagramId = checkComponentDiagramRelease(ciCode, viewType);
        }
        return generalPushSvc.publishDiagram(diagramId, releaseDesc, dirId, releaseDiagramId, Boolean.FALSE, false);
    }

    private String checkComponentDiagramRelease(String ciCode, String viewType) {
        List<ESDiagramNode> nodeList = iamsEsDiagramNodeDao.getListByQuery(QueryBuilders.termQuery("ciCode.keyword", ciCode));
        if (CollectionUtils.isEmpty(nodeList)) {
            return null;
        }
        Set<Long> diagramIdList = nodeList.stream().map(ESDiagramNode::getDiagramId).collect(Collectors.toSet());
        List<ESDiagram> diagramList = diagramApiClient.getByIds(diagramIdList, Lists.newArrayList(Env.BM_COMPONENT_DIR_TYPE), Lists.newArrayList(1));
        if (CollectionUtils.isEmpty(diagramList)) {
            return null;
        }
        List<ESDiagram> releaseDiagram = diagramList.stream().filter(esDiagram -> viewType.equals(esDiagram.getViewType())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(releaseDiagram)) {
            return null;
        }
        return releaseDiagram.get(0).getDEnergy();
    }

    @Override
    public String createTestAndEntityRltByTestCiCode(String ciCode) {
        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        //获取源端id
        ESCISearchBean ciQuery = new ESCISearchBean();
        ciQuery.setPageNum(1);
        ciQuery.setPageSize(1);
        ciQuery.setOwnerCode(loginCode);
        ciQuery.setCiCodes(Lists.newArrayList(ciCode));
        Page<ESCIInfo> ciInfoPriPage = ciSwitchSvc.searchESCIByBean(ciQuery, LibType.PRIVATE);
        Long sourceCiId = null;
        ciQuery.setOwnerCode(null);
        Page<ESCIInfo> ciInfoDesignPage = ciSwitchSvc.searchESCIByBean(ciQuery, LibType.DESIGN);
        if (CollectionUtils.isEmpty(ciInfoDesignPage.getData())) {
            ciQuery.setCiCodes(Collections.emptyList());
            if (CollectionUtils.isEmpty(ciInfoPriPage.getData())) {
                throw new ServiceException("该对象不存在");
            }
            ciQuery.setCiPrimaryKeys(Lists.newArrayList(ciInfoPriPage.getData().get(0).getCiPrimaryKey()));
            if (!CollectionUtils.isEmpty(ciInfoPriPage.getData())) {
                ciQuery.setClassIds(Lists.newArrayList(ciInfoPriPage.getData().get(0).getClassId()));
            }
            ciInfoDesignPage = ciSwitchSvc.searchESCIByBean(ciQuery, LibType.DESIGN);
            if (CollectionUtils.isEmpty(ciInfoDesignPage.getData())) {
                return "该任务尚未发布！";
            }
        }
        if (CollectionUtils.isEmpty(ciInfoPriPage.getData())) {
            if (CollectionUtils.isNotEmpty(ciInfoDesignPage.getData())) {
                List<ESCIInfo> designCi = ciInfoDesignPage.getData();
                CcCiInfo ciInfoById = ciSwitchSvc.getCiInfoById(designCi.get(0).getId(), LibType.DESIGN);
                ciInfoById.getCi().setOwnerCode(loginCode);
                ciInfoById.getCi().setId(null);
                sourceCiId = ciSwitchSvc.saveOrUpdateCI(ciInfoById, LibType.PRIVATE);
            }
        } else {
            sourceCiId = ciInfoPriPage.getData().get(0).getId();
        }
        String designCiCode = ciInfoDesignPage.getData().get(0).getCiCode();
        //1.获取目录信息
//        List<EamDiagramCatalog> catalogList = diagramCatalogSvc.selectByAssetCodes(Lists.newArrayList(designCiCode), loginCode, LibType.DESIGN);
        List<EamCategory> categoryList = categorySvc.selectListByCiCodes(null, Lists.newArrayList(designCiCode), null, LibType.DESIGN);
        if (CollectionUtils.isEmpty(categoryList)) {
            return "该任务对应视图不存在！";
        }
        EamCategory catalog = categoryList.get(0);
        //2.获取视图信息
        //任务CI对应视图
        String diagramId = catalog.getDiagramId();
        if (BinaryUtils.isEmpty(diagramId)) {
            return "该任务定义任务主视图未创建";
        }
        Long diagramInfo = diagramApiClient.queryDiagramInfoByEnergy(diagramId);
        List<ESDiagramDTO> esDiagramDTOS = diagramApiClient.queryDiagramInfoByIds(new Long[]{diagramInfo}, null, false, false);
        if (CollectionUtils.isEmpty(esDiagramDTOS)) {
            throw new ServiceException("该任务视图不存在，ciCode:" + ciCode);
        }
        //3.解析视图中关系
        //关系集合
        Set<String> rltCodes = EamDiagramUtils.getDiagramRltList(Lists.newArrayList(esDiagramDTOS.get(0).getDiagram()));
        //4.将关系源端元素替换未testCiCode保存
        JSONObject componentConfig = bmConfigSvc.getBusComponentConfig();
        if (BinaryUtils.isEmpty(componentConfig)) {
            throw new ServiceException("缺少业务组件相关配置:BUS_COMPONENT_CONFIG,请添加！");
        }
        if (CollectionUtils.isNotEmpty(rltCodes)) {
            ESRltSearchBean rltSearchBean = new ESRltSearchBean();
            rltSearchBean.setRltUniqueCodes(rltCodes);

            List<EamCiRltDTO> ciRltInfos = ciRltSwitchSvc.searchRltByRltCodes(rltSearchBean, LibType.DESIGN);

            //创建私有库的目标端元素
            Long entityClassId = getClassIdByName(componentConfig.getString(Env.BM_ENTITY));
            List<CcCiInfo> targetCcCiInfo = ciRltInfos.stream().map(CcCiRltInfo::getTargetCiInfo)
                    .filter(targetCiInfo -> targetCiInfo.getCiClass().getId().equals(entityClassId)).distinct().collect(Collectors.toList());

            List<CcCiInfo> sourceCiInfo = ciRltInfos.stream().map(CcCiRltInfo::getSourceCiInfo)
                    .filter(ciInfo -> ciInfo.getCiClass().getId().equals(entityClassId)).distinct().collect(Collectors.toList());
            targetCcCiInfo.addAll(sourceCiInfo);
            Map<String, CcCiInfo> targetDesignCi = targetCcCiInfo.stream().collect(Collectors.toMap(ccCiInfo -> ccCiInfo.getCi().getCiCode(), ccCiInfo -> ccCiInfo, (e1, e2) -> e1));
            Set<String> ciCodes = targetDesignCi.keySet();
            List<CcCiInfo> entityCIList = new ArrayList<>();
            for (String code : ciCodes) {
                entityCIList.add(targetDesignCi.get(code));
            }
            targetDesignCi = entityCIList.stream().collect(Collectors.toMap(ccCiInfo -> ccCiInfo.getCi().getCiCode(), ccCiInfo -> ccCiInfo, (e1, e2) -> e1));
            Map<String, EamCiRltDTO> entityRltMap = new HashMap<>();
            for (EamCiRltDTO ciRltInfo : ciRltInfos) {
                String sourceCiCod = ciRltInfo.getSourceCiInfo().getCi().getCiCode();
                String targetCiCode = ciRltInfo.getTargetCiInfo().getCi().getCiCode();
                if (ciCodes.contains(sourceCiCod) || ciCodes.contains(targetCiCode)) {
                    String rltCiCode = ciRltInfo.getCiRlt().getCiCode();
                    entityRltMap.put(rltCiCode, ciRltInfo);
                }
            }
            if (CollectionUtils.isNotEmpty(ciCodes)) {
                //查询私有库中不存在的CI进行检出
                ESCISearchBean esciSearchBean = new ESCISearchBean();
                esciSearchBean.setPageNum(1);
                esciSearchBean.setPageSize(ciCodes.size());
                esciSearchBean.setOwnerCode(loginCode);
                esciSearchBean.setCiCodes(new ArrayList<>(ciCodes));
                Page<ESCIInfo> ciPrivate = ciSwitchSvc.searchESCIByBean(esciSearchBean, LibType.PRIVATE);
                if (ciCodes.size() > ciPrivate.getTotalRows()) {
                    //检出私有库数据
                    List<CcCiInfo> createCis = new ArrayList<>();
                    if (ciPrivate.getTotalRows() == 0) {
                        createCis.addAll(entityCIList);
                    } else {
                        List<String> privateCiCode = ciPrivate.getData().stream().map(CcCi::getCiCode).collect(Collectors.toList());
                        for (String ciCodePri : privateCiCode) {
                            targetDesignCi.remove(ciCodePri);
                        }
                        createCis.addAll(targetDesignCi.values());
                    }
                    if (CollectionUtils.isNotEmpty(createCis)) {
                        saveOrUpdateCiByDesignCIInfo(entityCIList);
                    }
                }
            }
            //检验私有库关系是否创建
            ESRltSearchBean bean = new ESRltSearchBean();
            bean.setSourceCiCodes(Sets.newHashSet(ciCode));
            bean.setOwnerCode(loginCode);
            Page<CcCiRltInfo> privateRltPage = ciRltSwitchSvc.searchRltByBean(bean, LibType.PRIVATE);
            HashSet<BindCiRltRequestDto> requestDtos = new HashSet<>();
            if (CollectionUtils.isNotEmpty(privateRltPage.getData())) {
                //私有库关系不为空，创建不存在关系
                List<CcCiRltInfo> privateRlts = privateRltPage.getData();
                for (CcCiRltInfo privateRlt : privateRlts) {
                    String rltCiCode = privateRlt.getCiRlt().getCiCode();
                    entityRltMap.remove(rltCiCode);
                }
            }
            Collection<EamCiRltDTO> createRlts = entityRltMap.values();
            //创建设计库中存在关系
            for (CcCiRltInfo ciRltInfo : createRlts) {
                //关系分类 是 操作C，操作R，操作U,使用
                BindCiRltRequestDto requestDto = new BindCiRltRequestDto();
                String designTargetCiCode = ciRltInfo.getTargetCiInfo().getCi().getCiCode();
                String sourceCiCode = ciRltInfo.getSourceCiInfo().getCi().getCiCode();

                Page<ESCIInfo> ciTargetPrivateInfoPage;
                if (ciCodes.contains(designTargetCiCode)) {
                    ESCISearchBean ciTargetQuery = new ESCISearchBean();
                    ciTargetQuery.setPageNum(1);
                    ciTargetQuery.setPageSize(1);
                    ciTargetQuery.setOwnerCode(loginCode);
                    ciTargetQuery.setCiCodes(Lists.newArrayList(designTargetCiCode));
                    ciTargetPrivateInfoPage = ciSwitchSvc.searchESCIByBean(ciTargetQuery, LibType.PRIVATE);
                    if (CollectionUtils.isEmpty(ciTargetPrivateInfoPage.getData())) {
                        log.error("私有库不存在该实体，ciCode:" + designTargetCiCode);
                        continue;
                    }
                } else {
                    ESCISearchBean ciTargetQuery = new ESCISearchBean();
                    ciTargetQuery.setPageNum(1);
                    ciTargetQuery.setPageSize(1);
                    ciTargetQuery.setOwnerCode(loginCode);
                    ciTargetQuery.setCiCodes(Lists.newArrayList(sourceCiCode));
                    ciTargetPrivateInfoPage = ciSwitchSvc.searchESCIByBean(ciTargetQuery, LibType.PRIVATE);
                    if (CollectionUtils.isEmpty(ciTargetPrivateInfoPage.getData())) {
                        log.error("私有库不存在该实体，ciCode:" + designTargetCiCode);
                        continue;
                    }
                }

                Long targetId = ciTargetPrivateInfoPage.getData().stream().map(ESCIInfo::getId).filter(id -> !BinaryUtils.isEmpty(id)).findFirst().orElse(null);
                Long rltClassId = ciRltInfo.getCiRlt().getClassId();
                requestDto.setSourceCiId(sourceCiId);
                requestDto.setTargetCiId(targetId);
                requestDto.setOwnerCode(loginCode);
                requestDto.setRltClassId(rltClassId);
                requestDto.setAttrs(ciRltInfo.getAttrs());
                requestDto.setRepetitionError(false);
                requestDtos.add(requestDto);
            }

            if (BinaryUtils.isEmpty(requestDtos)) {
                log.error("创建关系为空");
                return "建立关系失败！";
            }
            for (BindCiRltRequestDto requestDto : requestDtos) {
                iamsCIRltPrivateSvc.bindCiRlt(requestDto);
            }
        }
        return "创建该任务关系成功！";
    }


    /**
     * 将目标端设计库元素备份到私有库
     */
    private void saveOrUpdateCiByDesignCIInfo(List<CcCiInfo> ciList) {

        Optional<CcCiInfo> optional = ciList.stream().filter(each -> BinaryUtils.isEmpty(each.getCi().getCiCode())).findAny();
        if (optional.isPresent()) {
            throw new BinaryException("存在ciCode为空的元素");
        }
        Set<Long> classIds = ciList.stream().map(CcCiInfo::getCi).map(CcCi::getClassId).filter(classId -> !BinaryUtils.isEmpty(classId)).collect(Collectors.toSet());

        SysUser user = SysUtil.getCurrentUserInfo();
        String loginCode = user.getLoginCode();
        ciList.forEach(ci -> {
            ci.getCi().setId(null);
            ci.getCi().setOwnerCode(loginCode);
        });
        ciSwitchSvc.saveOrUpdateBatchCI(EamUtil.coverCiInfoList(ciList), new ArrayList<>(classIds), loginCode, loginCode, LibType.PRIVATE);
    }

    @Override
    public List<CcCiRltInfo> getTargetCiAndRltBySourceCiCode(String ciCode,String ownerCode) {
        ESCISearchBean ciESBean = new ESCISearchBean();
        ciESBean.setCiCodes(Lists.newArrayList(ciCode));
        Page<ESCIInfo> designCiPage = ciSwitchSvc.searchESCIByBean(ciESBean, LibType.DESIGN);
        String designCiCode = ciCode;
        if (CollectionUtils.isEmpty(designCiPage.getData())) {
            ciESBean.setOwnerCode(ownerCode);
            Page<ESCIInfo> privateCiPage = ciSwitchSvc.searchESCIByBean(ciESBean, LibType.PRIVATE);
            ESCIInfo esciInfo = privateCiPage.getData().get(0);
            ciESBean.setCiCodes(Collections.emptyList());
            ciESBean.setCiPrimaryKeys(Lists.newArrayList(esciInfo.getCiPrimaryKey()));
            Page<ESCIInfo> primaryDesignCi = ciSwitchSvc.searchESCIByBean(ciESBean, LibType.DESIGN);
            if (CollectionUtils.isEmpty(primaryDesignCi.getData())) {
                return Collections.emptyList();
            }
            designCiCode = primaryDesignCi.getData().get(0).getCiCode();
        }
        ESRltSearchBean bean = new ESRltSearchBean();
        bean.setSourceCiCodes(Sets.newHashSet(designCiCode));
        JSONObject componentConfig = bmConfigSvc.getBusComponentConfig();
        if (BinaryUtils.isEmpty(componentConfig)) {
            throw new ServiceException("缺少业务组件相关配置:BUS_COMPONENT_CONFIG,请添加！");
        }
        Long entityClassId = getClassIdByName(componentConfig.getString(Env.BM_ENTITY));
        bean.setTargetClassIds(Lists.newArrayList(entityClassId));
        //查询设计库中的任务与实体关系
        Page<CcCiRltInfo> designPage = ciRltSwitchSvc.searchRltByBean(bean, LibType.DESIGN);
        Set<String> rltCiCodes = new HashSet<>();
        if (CollectionUtils.isNotEmpty(designPage.getData())) {
            rltCiCodes = designPage.getData().stream().map(ccCiRltInfo -> ccCiRltInfo.getCiRlt().getCiCode()).collect(Collectors.toSet());
        }
        bean.setOwnerCode(ownerCode);
        bean.setSourceCiCodes(Sets.newHashSet(ciCode));
        Page<CcCiRltInfo> privatePage = ciRltSwitchSvc.searchRltByBean(bean, LibType.PRIVATE);
        Set<String> rltPrivateCiCodes = new HashSet<>();
        if (CollectionUtils.isNotEmpty(privatePage.getData())) {
            rltPrivateCiCodes = privatePage.getData().stream().map(ccCiRltInfo -> ccCiRltInfo.getCiRlt().getCiCode()).collect(Collectors.toSet());
        }
        rltCiCodes.removeAll(rltPrivateCiCodes);
        if (CollectionUtils.isNotEmpty(rltCiCodes)) {
            //创建关系
            Set<String> finalRltCiCodes = rltCiCodes;
            List<CcCiRltInfo> createRltCi = designPage.getData().stream().filter(each -> finalRltCiCodes.contains(each.getCiRlt().getCiCode())).collect(Collectors.toList());
            Map<String, String> rltMappingCi = createRltCi.stream().collect(Collectors.toMap(each -> each.getCiRlt().getCiCode(), each -> each.getTargetCiInfo().getCi().getCiCode()));
            Collection<String> values = rltMappingCi.values();
            ESCISearchBean ciBean = new ESCISearchBean();
            ciBean.setCiCodes(new ArrayList<>(values));
            ciBean.setOwnerCode(ownerCode);
            Page<ESCIInfo> targetCi = ciSwitchSvc.searchESCIByBean(ciBean, LibType.PRIVATE);
            List<CcCiInfo> createTargetCi = new ArrayList<>();
            if (targetCi.getData().size() < values.size()) {
                //创建目标端对象
                List<String> privateTargetCi = targetCi.getData().stream().map(CcCi::getCiCode).collect(Collectors.toList());
                values.removeAll(privateTargetCi);
                if (CollectionUtils.isNotEmpty(values)) {
                    createTargetCi = designPage.getData().stream().map(CcCiRltInfo::getTargetCiInfo)
                            .filter(targetCiInfo -> values.contains(targetCiInfo.getCi().getCiCode())).collect(Collectors.toList());
                    saveOrUpdateCiByDesignCIInfo(createTargetCi);
                }
            }
            ArrayList<String> ciCodes = new ArrayList<>(rltMappingCi.values());
            ciCodes.add(ciCode);
            ciBean.setCiCodes(new ArrayList<>(ciCodes));
            Page<ESCIInfo> createRltTargetCi = ciSwitchSvc.searchESCIByBean(ciBean, LibType.PRIVATE);
            List<ESCIInfo> targetCiList = createRltTargetCi.getData();
            if (targetCiList.size() < ciCodes.size()&&CollectionUtils.isNotEmpty(createTargetCi)) {
                //根据业务主键查询
                List<String> primaryKeys = createTargetCi.stream().map(ccCiInfo -> ccCiInfo.getCi().getCiPrimaryKey()).collect(Collectors.toList());
                List<Long> classIds = createTargetCi.stream().map(ccCiInfo -> ccCiInfo.getCiClass().getId()).collect(Collectors.toList());
                ciBean.setCiCodes(Collections.emptyList());
                ciBean.setCiPrimaryKeys(primaryKeys);
                ciBean.setClassIds(classIds);
                Page<ESCIInfo> primaryKeysCiPage = ciSwitchSvc.searchESCIByBean(ciBean, LibType.PRIVATE);
                targetCiList.addAll(primaryKeysCiPage.getData());
            }
            Map<String, Long> ciCodeMappingId = targetCiList.stream().collect(Collectors.toMap(CcCi::getCiCode, CcCi::getId, (k1, k2) -> k1));
            Map<String, Long> primaryKeyMap = targetCiList.stream().collect(Collectors.toMap(CcCi::getCiPrimaryKey, CcCi::getId, (k1, k2) -> k1));
            HashSet<BindCiRltRequestDto> requestDtos = new HashSet<>();
            for (CcCiRltInfo rltInfo : createRltCi) {
                if(BinaryUtils.isEmpty(ciCodeMappingId.get(ciCode))){
                    continue;
                }
                BindCiRltRequestDto requestDto = new BindCiRltRequestDto();
                requestDto.setSourceCiId(ciCodeMappingId.get(ciCode));
                Long targetCiId = ciCodeMappingId.get(rltInfo.getTargetCiInfo().getCi().getCiCode());
                if(BinaryUtils.isEmpty(targetCiId)){
                    targetCiId = primaryKeyMap.get(rltInfo.getTargetCiInfo().getCi().getCiPrimaryKey());
                }
                //如果目标端为空
                requestDto.setTargetCiId(targetCiId);
                requestDto.setOwnerCode(ownerCode);
                requestDto.setRltClassId(rltInfo.getCiRlt().getClassId());
                requestDto.setAttrs(rltInfo.getAttrs());
                requestDto.setRepetitionError(true);
                requestDtos.add(requestDto);
            }
            if(!BinaryUtils.isEmpty(requestDtos)){
                ciRltSwitchSvc.bindCiRlts(requestDtos, LibType.PRIVATE);
            }
            privatePage = ciRltSwitchSvc.searchRltByBean(bean, LibType.PRIVATE);
        }
        return privatePage.getData();
    }

    @Override
    public ModuleFieldInfo quickDrawing(String energy, String ciCode) {
        ModuleFieldInfo result = new ModuleFieldInfo();
        //查询制品
        Long diagramId = diagramApiClient.queryDiagramInfoByEnergy(energy);
        ESDiagramDTO diagramDTO = diagramApiClient.queryESDiagramInfoById(diagramId, null, false);
        SysUser creator = diagramDTO.getCreator();
        String artifactId = diagramDTO.getDiagram().getViewType();
        if (BinaryUtils.isEmpty(artifactId)) {
            throw new ServiceException("非制品创建视图！");
        }
        String configType = bmConfigSvc.getConfigType(Env.BM_BELONG_ZJ);
        if (BinaryUtils.isEmpty(configType)) {
            throw new ServiceException("视图配置项" + Env.BM_BELONG_ZJ + "不存在!");
        }
        JSONObject jsonObject = JSON.parseObject(configType);
        String rltClassName = jsonObject.get("rltClass").toString();
        //查询归属于关系
        CCcCiClass rltCdt = new CCcCiClass();
        rltCdt.setClassName(rltClassName);
        List<CcCiClassInfo> rltClass = rltClassApiSvc.getRltClassByCdt(rltCdt);
        if (BinaryUtils.isEmpty(rltClass)) {
            throw new ServiceException(rltClassName + "关系分类不存在!");
        }
        Long rltClassId = rltClass.get(0).getCiClass().getId();
        //源端分类名称
        String sourceClassName = jsonObject.get("sourceClass").toString();
        //目标端分类名称
        String targetClassName = jsonObject.get("targetClass").toString();
        CCcCiClass queryClass = new CCcCiClass();
        queryClass.setClassNames(new String[]{sourceClassName, targetClassName});
        List<CcCiClassInfo> ciClassList = iciClassApiSvc.queryClassByCdt(queryClass);
        Map<String, CcCiClass> classNameMap = ciClassList.stream().map(CcCiClassInfo::getCiClass).collect(Collectors.toMap(CcCiClass::getClassName, each -> each, (key1, key2) -> key2));
        CcCiClass sourceClass = classNameMap.get(sourceClassName);
        CcCiClass targetClass = classNameMap.get(targetClassName);
        if (BinaryUtils.isEmpty(sourceClass) || BinaryUtils.isEmpty(targetClass)) {
            throw new ServiceException("源端分类'" + sourceClassName + "'或目标端分类'" + targetClassName + "'不存在!");
        }

        //自有组件查询查询归属于关系分类/设计库(源端业务组件目标端业务领域)
        List<CcCiRltInfo> belongRltList = ciRltSwitchSvc.getRltInfoByClassId(Collections.singletonList(rltClassId), sourceClass.getId(), targetClass.getId(), null, LibType.DESIGN);
        Map<String, CcCiInfo> insideMap = belongRltList.stream().filter(rltInfo -> {
            String targetCiCode = rltInfo.getTargetCiInfo().getCi().getCiCode();
            return targetCiCode.equals(ciCode);
        }).map(CcCiRltInfo::getSourceCiInfo).collect(Collectors.toMap(each -> each.getCi().getCiCode(), each -> each, (k1, k2)->k2));
        List<CcCiInfo> inside = Lists.newArrayList(insideMap.values());
        result.setInside(inside);
        //外部组件查询制品配置的第一个分类并过滤掉自有组件
        List<EamArtifactElementVo> artifactNodes = eamArtifactColumnSvc.queryAllColumns(new ElementDto(Long.parseLong(artifactId), ArtifactType.RLT_TYPE.val()));
        if (!BinaryUtils.isEmpty(artifactNodes)) {
            List<String> elements = artifactNodes.stream().map(EamArtifactElementVo::getElements).flatMap(Collection::stream).collect(Collectors.toList());
            List<EamArtifactRltVo> rltList = elements.stream().map(s -> JSON.parseObject(s, EamArtifactRltVo.class)).collect(Collectors.toList());
            List<Long> rltId = new ArrayList<>();
            for (EamArtifactRltVo vo : rltList) {
                Long sourceId = vo.getSourceCiInfo().getId();
                Long targetId = vo.getTargetCiInfo().getId();
                //这里取源端和目标端相反的关系分类
                if (sourceClass.getId().equals(targetId) && targetClass.getId().equals(sourceId)) {
                    rltId.add(vo.getRltClassInfo().getCiClass().getId());
                }
            }
            List<CcCiInfo> outside = Collections.emptyList();
            List<String> filterCiCode = inside.stream().map(each -> each.getCi().getCiCode()).collect(Collectors.toList());
            //查询组件是设计库的
            if (!BinaryUtils.isEmpty(rltId)) {
                //查询出设计库的所有源端ci,用于过滤出已发布的ci自动成图
                ESCISearchBean bean = new ESCISearchBean();
                bean.setPageNum(1);
                bean.setPageSize(1000);
                bean.setClassIds(Collections.singletonList(sourceClass.getId()));
                Page<ESCIInfo> designCiPage = ciSwitchSvc.searchESCIByBean(bean, LibType.DESIGN);
                List<String> designCiCode = designCiPage.getData().stream().map(CcCi::getCiCode).collect(Collectors.toList());

                List<CcCiRltInfo> outsideRltList = ciRltSwitchSvc.getRltInfoByClassId(rltId, targetClass.getId(), sourceClass.getId(), creator.getLoginCode(), LibType.PRIVATE);
                Map<String, CcCiInfo> outsideMap = outsideRltList.stream().filter(rltInfo -> {
                    String source = rltInfo.getSourceCiInfo().getCi().getCiCode();
                    String target = rltInfo.getTargetCiInfo().getCi().getCiCode();
                    return source.equals(ciCode) && !filterCiCode.contains(target) && designCiCode.contains(target);
                }).map(CcCiRltInfo::getTargetCiInfo).collect(Collectors.toMap(each -> each.getCi().getCiCode(), each -> each, (k1, k2)->k2));
                outside = Lists.newArrayList(outsideMap.values());
            }
            result.setOutside(outside);
        }
        return result;
    }

    /**
     * 校验业务组件所属领域（自有组件or外部组件）
     */
    @Override
    public Map<String, Boolean> checkModuleDomain(String source, List<String> ciCodes){
        //查询关系分类-归属于,源端是业务组件，目标端是业务领域
        String configType = bmConfigSvc.getConfigType(Env.BM_BELONG_ZJ);
        if (BinaryUtils.isEmpty(configType)) {
            throw new ServiceException("视图配置项" + Env.BM_BELONG_ZJ + "不存在!");
        }
        JSONObject jsonObject = JSON.parseObject(configType);
        String rltClassName = jsonObject.get("rltClass").toString();
        //查询归属于关系
        CCcCiClass rltCdt = new CCcCiClass();
        rltCdt.setClassName(rltClassName);
        List<CcCiClassInfo> rltClass = rltClassApiSvc.getRltClassByCdt(rltCdt);
        if (BinaryUtils.isEmpty(rltClass)) {
            throw new ServiceException(rltClassName + "关系分类不存在!");
        }
        Long rltClassId = rltClass.get(0).getCiClass().getId();
        //源端分类名称
        String sourceClassName = jsonObject.get("sourceClass").toString();
        //目标端分类名称
        String targetClassName = jsonObject.get("targetClass").toString();
        CCcCiClass queryClass = new CCcCiClass();
        queryClass.setClassNames(new String[]{sourceClassName, targetClassName});
        List<CcCiClassInfo> ciClassList = iciClassApiSvc.queryClassByCdt(queryClass);
        Map<String, CcCiClass> classNameMap = ciClassList.stream().map(CcCiClassInfo::getCiClass).collect(Collectors.toMap(CcCiClass::getClassName, each -> each, (key1, key2) -> key2));
        CcCiClass sourceClass = classNameMap.get(sourceClassName);
        CcCiClass targetClass = classNameMap.get(targetClassName);
        if (BinaryUtils.isEmpty(sourceClass) || BinaryUtils.isEmpty(targetClass)) {
            throw new ServiceException("源端分类'" + sourceClassName + "'或目标端分类'" + targetClassName + "'不存在!");
        }
        //自有组件查询查询归属于关系分类/设计库(源端业务组件目标端业务领域)
        List<CcCiRltInfo> belongRltList = ciRltSwitchSvc.getRltInfoByClassId(Collections.singletonList(rltClassId), sourceClass.getId(), targetClass.getId(), null, LibType.DESIGN);
        Set<String> sourceCiCodes = belongRltList.stream().filter(each->{
            String ciCode = each.getTargetCiInfo().getCi().getCiCode();
            return source.equals(ciCode);
        }).map(each -> each.getSourceCiInfo().getCi().getCiCode()).collect(Collectors.toSet());
        Map<String, Boolean> result = new TreeMap<>();
        for (String ciCode : ciCodes) {
            if(sourceCiCodes.contains(ciCode)){
                result.put(ciCode, true);
                continue;
            }
            result.put(ciCode, false);
        }
        return result;
    }
}
